package top.hmtools.security;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.math.BigInteger;
import java.nio.charset.Charset;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;

/**
 * 综合的公共加密算法类
 * <br>支持：
 * <br>MD2
 * <br>MD5
 * <br>SHA-1
 <br>SHA-224
 <br>SHA-256
 <br>SHA-384
 <br>SHA-512
 * 
 * @author Jianghaibo
 *
 */
public class SecurityTools {

    /**
     * 获取输入流的加密值，结果为英文字母小写 <br>
     * 方法说明： getLowStr <br>
     * 输入参数说明： <br>
     * @param inputStream <br>
     * @return <br>
     * 输出参数说明： <br>
     * String
     *
     */
    public  static String getLowStr(InputStream inputStream,ESecurityName securityName) {
        try {
            MessageDigest messageDigest = MessageDigest.getInstance(securityName.toString());
            byte[] buffer = new byte[8192];
            int length;
            while ((length = inputStream.read(buffer)) != -1) {
                messageDigest.update(buffer, 0, length);
            }
            BigInteger bi = new BigInteger(1, messageDigest.digest());
            return bi.toString(16).toLowerCase();
        } catch (Exception e) {
            return null;
        } finally {
            try {
                if (inputStream != null)
                    inputStream.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    /**
     * 获取文件的加密值，结果为英文字母小写
    * <br>方法说明：                    getLowStr
    * <br>输入参数说明：           
    * <br>@param file
    * <br>@return
    * <br>输出参数说明：
    * <br>String           
    *
     */
    public final static String getLowStr(File file,ESecurityName securityName) {
        try {
            FileInputStream fileInputStream = new FileInputStream(file);
            return getLowStr(fileInputStream,securityName);
        } catch (FileNotFoundException e) {
            return null;
        }
    }

    /**
     * 获取字节码的加密值，结果为英文字母小写
    * <br>方法说明：                    getLowStr
    * <br>输入参数说明：           
    * <br>@param bytes
    * <br>@return
    * <br>输出参数说明：
    * <br>String           
    *
     */
    public final static String getLowStr(byte[] bytes,ESecurityName securityName) {
        MessageDigest messageDigest = null;
        try {
            messageDigest = MessageDigest.getInstance(securityName.toString());
        } catch (NoSuchAlgorithmException e) {
            return null;
        }  
        messageDigest.update(bytes); 
        byte[] resultBytes = messageDigest.digest();
     // 获得密文
        BigInteger bi = new BigInteger(1, resultBytes); 
        return bi.toString(16).toLowerCase();
    }

    /**
     * 获取字符串的加密值，结果为英文字母小写
    * <br>方法说明：                    getLowStr
    * <br>输入参数说明：           
    * <br>@param str
    * <br>@return
    * <br>输出参数说明：
    * <br>String           
    *
     */
    public final static String getLowStr(String str,ESecurityName securityName) {
        return getLowStr(str.getBytes(),securityName);
    }

    /**
     * 获取字符串，指定字符编码的加密值，结果为英文字母小写
    * <br>方法说明：                    getLowStr
    * <br>输入参数说明：           
    * <br>@param str
    * <br>@param charset
    * <br>@return
    * <br>输出参数说明：
    * <br>String           
    *
     */
    public final static String getLowStr(String str,Charset charset,ESecurityName securityName) {
        return getLowStr(str.getBytes(charset),securityName);
    }
    
    /**
     * 加密方式枚举
     * @author Jianghaibo
     *
     */
    enum ESecurityName{
        
        MD2("MD2"),
        MD5("MD5"),
        SHA1("SHA-1"),
        SHA224("SHA-224"),
        SHA256("SHA-256"),
        SHA384("SHA-384"),
        SHA512("SHA-512")
        ;
        
        private String name;
        ESecurityName(String name){
            this.name=name;
        }
        /**
         * <br>方法说明
         * <br>输入参数说明
         * <br>输出参数说明
         */
        @Override
        public String toString() {
            return this.name;
        }
    }
}
